/**
 * @author nttdocomo
 */
define(function(require) {
	aries.augmentString('aries.container.DockingContainer', aries.Class.extend({

		/**
		 * Adds docked item(s) to the container.
		 * @param {Object/Object[]} component The Component or array of components to add. The components
		 * must include a 'dock' parameter on each component to indicate where it should be docked ('top', 'right',
		 * 'bottom', 'left').
		 * @param {Number} pos (optional) The index at which the Component will be added
		 */
		addDocked : function(items, pos) {
			var me = this, i = 0, item, length;

			items = me.prepareItems(items);
			length = items.length;

			for (; i < length; i++) {
				item = items[i];
				item.dock = item.dock || 'top';

				if (pos !== undefined) {
					me.dockedItems.insert(pos + i, item);
					/*me.dockedItems.add(item, {
						at : pos + i
					});*/
				} else {
					me.dockedItems.add(item);
				}
				if (item.onAdded !== aries.emptyFn) {
					item.onAdded(me, i);
				}
				if (me.onDockedAdd !== aries.emptyFn) {
					me.onDockedAdd(item);
				}
			}

			if (me.rendered && !me.suspendLayout) {
				me.updateLayout();
			}
			return items;
		},

		doRenderDockedItems : function(comp,after) {
			// Careful! This method is bolted on to the frameTpl and renderTpl so all we get for
			// context is the renderData! The "this" pointer is either the frameTpl or the
			// renderTpl instance!

			// Due to framing, we will be called in two different ways: in the frameTpl or in
			// the renderTpl. The frameTpl version enters via doRenderFramingDockedItems which
			// sets "$skipDockedItems" on the renderTpl's renderData.
			//
			var me = comp, layout = me.componentLayout, items, tree, html = [];

			if (me.getDockedModels/* && !renderData.$skipDockedItems*/) {
				items = me.getDockedModels('render', !after);
				//tree = items && layout.getItemsRenderTree(items);
				_.each(items,function(item){
					html.push(item.html())
				});
				return html.join("")

				/*if (tree) {
					Ext.DomHelper.generateMarkup(tree, out);
				}*/
			}
			return "";
		},
		getDockedModels : function(order, beforeBody) {
			var me = this, all = me.dockedItems.models, sort = all && all.length && order !== false, renderOrder, dock, dockedItems, i, isBefore, length;

			if (beforeBody == null) {
				dockedItems = sort ? all.slice() : all;
			} else {
				dockedItems = [];

				for ( i = 0, length = all.length; i < length; ++i) {
					dock = all[i].dock;
					isBefore = (dock == 'top' || dock == 'left');
					if ( beforeBody ? isBefore : !isBefore) {
						dockedItems.push(all[i]);
					}
				}

				sort = sort && dockedItems.length;
			}

			if (sort) {
				renderOrder = ( order = order || 'render') == 'render';
				dockedItems.sort(function(a, b) {
					var aw, bw;

					// If the two items are on opposite sides of the body, they must not be sorted by any weight value:
					// For rendering purposes, left/top *always* sorts before right/bottom
					if (renderOrder && (( aw = me.owner.dockOrder[a.dock]) !== ( bw = me.owner.dockOrder[b.dock]))) {

						// The two dockOrder values cancel out when two items are on opposite sides.
						if (!(aw + bw)) {
							return aw - bw;
						}
					}

					aw = me.getItemWeight(a, order);
					bw = me.getItemWeight(b, order);
					if ((aw !== undefined) && (bw !== undefined)) {
						return aw - bw;
					}
					return 0;
				});
			}

			return dockedItems || [];
		},

		/**
		 * Retrieves an array of all currently docked Components.
		 *
		 * For example to find a toolbar that has been docked at top:
		 *
		 *     panel.getDockedItems('toolbar[dock="top"]');
		 *
		 * @param {String} selector A {@link Ext.ComponentQuery ComponentQuery} selector string to filter the returned items.
		 * @param {Boolean} beforeBody An optional flag to limit the set of items to only those
		 *  before the body (true) or after the body (false). All components are returned by
		 *  default.
		 * @return {Ext.Component[]} The array of docked components meeting the specified criteria.
		 */
		getDockedItems : function(selector, beforeBody) {
			var dockedItems = this.getComponentLayout().getDockedItems('render', beforeBody);

			if (selector && dockedItems.length) {
				dockedItems = Ext.ComponentQuery.query(selector, dockedItems);
			}

			return dockedItems;
		},
		initDockingItems : function() {
			var me = this, items = me.dockedItems;

			me.dockedItems = items.length ? new aries.util.AbstractMixedCollection(items) : new aries.util.AbstractMixedCollection;
			if (items) {
				me.addDocked(items);
			}
		},

		// Placeholder empty functions
		/**
		 * Invoked after a docked item is added to the Panel.
		 * @param {Ext.Component} component
		 * @template
		 * @protected
		 */
		onDockedAdd : aries.emptyFn,
		renderDockedItems : function() {
			return "renderDockedItems"
		},

		setupDockingRenderTpl : function(renderTpl) {
			renderTpl.renderDockedItems = this.doRenderDockedItems;
		},

		setupDockingRenderData : function(renderData) {
			renderData.renderDockedItems = this.doRenderDockedItems;
			return renderData;
		}
	}))
})
